package lock;

public class ReadWriteTester {

	public static void main(String[] args) {
		// ReadWriteLock lock = new FairReadWriteLock();
		ReadWriteLock lock = new ReadBiasLock();
		int nr = 10, nw = 5;
		int loopr = 20, loopw = 10;
		WriteTask[] writes = new WriteTask[nw];
		for (int i = 0; i < nw; ++i) {
			writes[i] = new WriteTask(i + 1, loopw, lock);
			new Thread(writes[i]).start();
		}
		ReadTask[] reads = new ReadTask[nr];
		for (int i = 0; i < nr; ++i) {
			reads[i] = new ReadTask(i + 1, loopr, lock);
			new Thread(reads[i]).start();
		}
	}

	static class ReadTask implements Runnable {
		int id;
		int loop;
		ReadWriteLock lock;

		public ReadTask(int id, int loop, ReadWriteLock lock) {
			this.id = id;
			this.loop = loop;
			this.lock = lock;
		}

		@Override
		public void run() {
			for (int i = 0; i < loop; ++i) {
				try {
					lock.readLock();
					 System.out.println("Thread " + id + " get read lock");
					for (int j = 0; j < 10; ++j) {
						// System.out.println("read threadId: " + id +
						// " count: "
						// + j);
						Thread.sleep(10);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					System.out.println("Thread " + id + " release read lock");
					lock.realseReadLock();
				}
			}
		}
	}

	static class WriteTask implements Runnable {
		int id;
		int loop;
		ReadWriteLock lock;

		public WriteTask(int id, int loop, ReadWriteLock lock) {
			this.id = id;
			this.loop = loop;
			this.lock = lock;
		}

		@Override
		public void run() {
			for (int i = 0; i < loop; ++i) {
				try {
					lock.writeLock();
					System.out.println("Thread " + id + " get write lock");
					for (int j = 0; j < 10; ++j) {
						// System.out.println("write threadId: " + id +
						// " count: "
						// + j);
						Thread.sleep(10);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					System.out.println("Thread " + id + " release write lock");
					lock.realseWriteLock();
				}
			}
		}
	}

}
